﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ArithmeticLibrary;
using Nolineq.Iterators;

namespace Nolineq.Methods
{
    /// <summary>
    /// Resic rovnic kombinovanou metodou.
    /// </summary>
    public class NewtonsHybridMethod : EquationSolver
    {
        /// <summary>
        /// Typ pro zvoleni pomale metody.
        /// </summary>
        public enum SlowMethodType
        { 
            BisectionMethod, SecantMethod
        }

        #region Fields

        /// <summary>
        /// Pomala, ale bezpecna metoda.
        /// </summary>
        Iterator slowMethod;

        /// <summary>
        /// Rychla, ale nebezpecna metoda.
        /// </summary>
        NewtonsIterator fastMethod;

        #endregion // Fields

        #region Constuctors

        public NewtonsHybridMethod(SlowMethodType type, Function function, double start, double end, double root, double precision, int maxSteps)
            : base(function, start, end, root, precision, maxSteps)
        {
            this.Name = "Kombinovaná metoda";
            this.Approximation = 0;

            if (type == SlowMethodType.BisectionMethod)
                slowMethod = new BisectionIterator(this);
            else if (type == SlowMethodType.SecantMethod)
                slowMethod = new SecantIterator(this);

            fastMethod = new NewtonsIterator(this);
        }

        #endregion

        /// <summary>
        /// Vyresi rovnici kombinovanou metodou.
        /// </summary>
        /// <param name="start">Zacatek intervalu.</param>
        /// <param name="end">Konec intervalu.</param>
        /// <param name="precision">Presnost.</param>
        /// <returns>Vrati reseni rovnice.</returns>
        public override Solution Solve()
        {
            int steps = 0;

            // zkusime iterovat newtnovou metodou
            if (!fastMethod.Iterate())
            {
                // jestli v nejakem kroku nejde newtonova metoda, 
                // tak to zkusime oditerovat metodou secen
                if (!slowMethod.Iterate())
                {
                   
                }
            }

            ++steps;

            // dokud se nepriblizime dost blizko ke korenu
            while (Math.Abs(Function.Evaluate(Approximation)) >= Precision && steps < MaxSteps)
            {
                if (!fastMethod.Iterate())
                {
                    if (!slowMethod.Iterate())
                    {
                    
                    }
                }

                ++steps;
            }

            // kontrola prekroceni limitu iteraci
            if (steps == MaxSteps)
                throw new UnsuitableMethodException("Překročen limit počtu iterací. Zkuste nastavit větší počet iterací, upravit počáteční parametry nebo zvolte jinou metodu.");
                
            return new Solution(Approximation, steps);
        }
    }
}
